/*******************************************************\
|* Author: Trevor Sundberg
\*******************************************************/

// Header protection
#pragma once
#ifndef SKUGO_EVENT_HANDLER_HPP
#define SKUGO_EVENT_HANDLER_HPP

// Includes
#include "SkugoDelegate.hpp"
#include <vector>

namespace Skugo
{
  // Using directives
  using std::vector;

  // Type-defines
  typedef void NoArguments;

  // An event handler is responsible for sending out events
  template <typename EventArg>
  class EventHandler
  {
  public:

    // Type-defines
    //typedef Delegate<EventArg*> EventDelegate;

    typedef void (*EventFn)(EventArg* arg, void* userData);
    struct EventDelegate
    {
      void*   UserData;
      EventFn Callback;
    };
    
    // Add a callback to the handler
    void Add(EventFn callback, void* userData)
    {
      EventDelegate delegate;
      delegate.Callback = callback;
      delegate.UserData = userData;
      mCallbacks.push_back(delegate);
    }

    // Remove is unfortunately not possible, since we cannot compare our delegates
    // We could potential compare delegates using a union trick, but it would take quite
    // a bit of work and would result in a non-standard implementation :/
    //void Remove(const Delegate<EventArg>& callback);

    // Clear all the callbacks
    void Clear()
    {
      mCallbacks.clear();
    }

    // Invoke the event handler
    void Invoke(EventArg* eventData)
    {
      // Loop through all the callbacks
      for (sizeType i = 0; i < mCallbacks.size(); ++i)
      {
        // Invoke each callback and pass in the event data
        auto& delegate = mCallbacks[i];
        delegate.Callback(eventData, delegate.UserData);
      }
    }

  private:

    // Store an array of all the callack delegates
    vector<EventDelegate> mCallbacks;
  };
}

// End header protection
#endif
